import json
import os

import pandas as pd
from datetime import datetime as datetime_
from datetime import timedelta
import statistics
from filelock import FileLock


IntervalMap = {
    'SECOND': timedelta(seconds=1),
    'SECOND2': timedelta(seconds=2),
    'SECOND3': timedelta(seconds=3),
    'SECOND4': timedelta(seconds=4),
    'SECOND5': timedelta(seconds=5),
    'SECOND6': timedelta(seconds=6),
    'SECOND10': timedelta(seconds=10),
    'SECOND12': timedelta(seconds=12),
    'SECOND15': timedelta(seconds=15),
    'SECOND20': timedelta(seconds=20),
    'SECOND30': timedelta(seconds=30),
    'MINUTE': timedelta(minutes=1),
    'MINUTE2': timedelta(minutes=2),
    'MINUTE3': timedelta(minutes=3),
    'MINUTE4': timedelta(minutes=4),
    'MINUTE5': timedelta(minutes=5),
    'MINUTE6': timedelta(minutes=6),
    'MINUTE10': timedelta(minutes=10),
    'MINUTE12': timedelta(minutes=12),
    'MINUTE15': timedelta(minutes=15),
    'MINUTE20': timedelta(minutes=20),
    'MINUTE30': timedelta(minutes=30),
    'HOUR': timedelta(hours=1),
    'HOUR2': timedelta(hours=2),
    'HOUR3': timedelta(hours=3),
    'HOUR4': timedelta(hours=4),
    'HOUR6': timedelta(hours=6),
    'HOUR8': timedelta(hours=8),
    'HOUR12': timedelta(hours=12),
    'DAILY': timedelta(hours=24)
}


def data_df_interval(data_df: pd.DataFrame):
    # 读取数据文件的前20组
    temp_df = data_df.head(20)
    temp_index_ls = temp_df.index.tolist()
    temp_timedelta_ls = []
    for i in range(len(temp_index_ls) - 1):
        temp_timedelta_ls.append(temp_index_ls[i + 1] - temp_index_ls[i])
    mode_value: timedelta = statistics.mode(temp_timedelta_ls)
    # 根据timedelta通过IntervalMap反向获取相应的Interval实例
    interval_ins = None
    interval_val = None
    for k, v in IntervalMap.items():
        if v == mode_value:
            interval_ins = v
            interval_val = k
            break
    if interval_ins is None:
        raise ValueError("获取数据文件的Interval实例失败。")

    return interval_val


def split_df_by_symbol(df: pd.DataFrame, alone_symbol=None):
    """
    如果DataFrame中存在'symbol'列，则按此列的值拆分DataFrame。
    否则，返回原始DataFrame。

    :param df: 输入的DataFrame。
    :return: 字典，键为'symbol'的值，值为对应的DataFrame，或者原始DataFrame。
    """

    def drop_repeat_index(df_f):
        """
        移除DataFrame中重复的索引行，但保留每组重复索引中的最后一行。
        """
        return_df = df_f.reset_index().drop_duplicates(subset='datetime', keep='last').set_index('datetime', drop=True)
        return return_df

    if 'symbol' in df.columns:
        # 按"symbol"的值拆分DataFrame
        df_dc = {symbol: drop_repeat_index(sub_df.drop(columns=['symbol'])) for symbol, sub_df in df.groupby('symbol')}
        return df_dc
    else:
        # 如果"symbol"列不存在
        if alone_symbol is None:
            return {"DDQ001": drop_repeat_index(df)}
        else:
            return {alone_symbol: drop_repeat_index(df)}


def read_dc_csv(path) -> dict:
    """仅用于读取时间序列的csv文件，且数据以时间为索引"""
    if os.path.exists(path):
        lock = FileLock(path + ".lock")
        with lock:
            data = pd.read_csv(path)
        # 将时间作为索引
        if "datetime" in data.columns:
            data = data.set_index('datetime', drop=True)
        elif '' in data.columns:
            data = data.set_index('', drop=True)
            data.index.name = "datetime"
        elif "Unnamed: 0" in data.columns:
            data = data.set_index("Unnamed: 0", drop=True)
            data.index.name = "datetime"
        else:
            raise ValueError("索引设置异常。")
        temp = str(data.index[0]).isdigit()
        if not temp:
            data.index = pd.to_datetime(data.index)
        else:
            data.index = pd.to_datetime(data.index, format="%Y%m%d")
        alone_symbol = os.path.basename(path).split('_')[1]

        data_split = split_df_by_symbol(data, alone_symbol=alone_symbol)
        return data_split
    else:
        return False


def gen_data_info(data_path):
    name = os.path.basename(data_path)
    data_df_dc: dict = read_dc_csv(data_path)
    symbol_ls = list(data_df_dc.keys())
    data_df = data_df_dc[symbol_ls[0]]
    data_len = data_df.__len__()
    if data_len == 0:
        interval_val = None
        data_modified_time = None
        start_time = None
        end_time = None
    else:
        # 从第一个symbol中获取文件相应的Interval
        interval_val = data_df_interval(data_df)

        # 获取文件的修改时间戳
        modified_timestamp = os.path.getmtime(data_path)

        # 将时间戳转换为日期格式
        data_modified_time = datetime_.fromtimestamp(modified_timestamp)
        # 数据起止时间
        start_time: datetime_ = data_df.index[0]
        end_time: datetime_ = data_df.index[-1]

    mk_data_info_dc = {"name": name,
                       "interval": interval_val,
                       "data_modified_time": data_modified_time,
                       "start_time": start_time,
                       "end_time": end_time,
                       "number": data_len,
                       "symbol": symbol_ls}
    return mk_data_info_dc

